package com.jt.www.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtil {
    public static final Logger log = LoggerFactory.getLogger(RedisUtil.class);
    private static final String SEPARATOR = "_";
    /**
     * 单个服务器出单查询缓存失效时间 默认超时时间10分钟
     */
    private static final long TIME_OUT = 600L;
    private static StringRedisTemplate redisTemplate;

    /**
     * 添加固定1个小时超时
     *
     * @param key
     * @return
     */
    public static Boolean setOneHoursLock(String key) {
        //判断key是否存在，如果存在，返回设置失败
        if (redisTemplate.hasKey(key)) {
            return false;
        }
        return redisTemplate.execute(new SessionCallback<Boolean>() {
            List<Object> exec = null;

            @Override
            @SuppressWarnings("unchecked")
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                redisTemplate.opsForValue().setIfAbsent(key, "1");
                redisTemplate.expire(key, 1, TimeUnit.HOURS);
                exec = operations.exec();
                if (exec.size() > 0) {
                    return (Boolean) exec.get(0);
                }
                return false;
            }
        });
    }

    /**
     * 删除锁
     *
     * @param keys
     */
    public static void delete(String... keys) {
        redisTemplate.delete(createLockKey(keys));
    }

    /**
     * 添加固定6个小时超时
     *
     * @param key
     * @return
     */
    public static Boolean setSixHoursLock(String key) {
        //判断key是否存在，如果存在，返回设置失败
        if (redisTemplate.hasKey(key)) {
            return false;
        }
        return redisTemplate.execute(new SessionCallback<Boolean>() {
            List<Object> exec = null;

            @Override
            @SuppressWarnings("unchecked")
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                redisTemplate.opsForValue().setIfAbsent(key, "1");
                redisTemplate.expire(key, 6, TimeUnit.HOURS);
                exec = operations.exec();
                if (exec.size() > 0) {
                    return (Boolean) exec.get(0);
                }
                return false;
            }
        });
    }

    /**
     * 设置缓存
     *
     * @param key
     * @return
     */
    public static Boolean setLock(String... key) {
        return setLock(createLockKey(key), "1", TIME_OUT);
    }

    /**
     * 设置缓存
     *
     * @param key
     * @param timeout 超时时间，单位秒
     * @return
     */
    public static Boolean setLock(final long timeout, String... key) {
        return setLock(createLockKey(key), "1", timeout);
    }

    /**
     * 设置缓存
     *
     * @param key
     * @param value
     * @param timeout 超时时间，单位秒
     * @return
     */
    public static Boolean setLock(String key, String value, final long timeout) {
        return setLock(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置缓存
     *
     * @param key
     * @param value
     * @param timeout  超时时间
     * @param timeUnit 时间单位
     * @return
     */
    public static Boolean setLock(String key, String value, final long timeout, TimeUnit timeUnit) {
        //判断key是否存在，如果存在，返回设置失败
        if (redisTemplate.hasKey(key)) {
            return false;
        }
        return redisTemplate.execute(new SessionCallback<Boolean>() {
            List<Object> exec = null;

            @Override
            @SuppressWarnings("unchecked")
            public Boolean execute(RedisOperations operations) throws DataAccessException {
                operations.multi();
                redisTemplate.opsForValue().setIfAbsent(key, value);
                redisTemplate.expire(key, timeout, timeUnit);
                exec = operations.exec();
                if (exec.size() > 0) {
                    return (Boolean) exec.get(0);
                }
                return false;
            }
        });
    }

    /**
     * 得到缓存值
     *
     * @param key
     * @return
     */
    public static String getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 数值型缓存计算
     *
     * @param key
     * @param val
     * @return
     */
    public static Long increment(String key, int val) {
        return redisTemplate.boundValueOps(key).increment(val);
    }

    /**
     * 生成缓存key
     *
     * @param keys
     * @return
     */
    public static String createLockKey(String... keys) {
        if (null == keys || keys.length == 0) {
            //默认的key
            return "EDU_DEFAULT_LOCK_KEY";
        }
        String retKey = keys[0];
        for (int i = 1; i < keys.length; i++) {
            retKey = retKey + SEPARATOR + keys[i];
        }
        return retKey;
    }

    @Autowired
    public void setRedisTemplate(StringRedisTemplate redisTemplate) {
        RedisUtil.redisTemplate = redisTemplate;
    }

}
